package com.boot.mgt.service.impl

import cn.hutool.core.bean.BeanUtil
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.boot.config.datasource.OracleDb
import com.boot.core.protocol.QueryRequestOfApp
import com.boot.core.result.ResultEnum
import com.boot.core.result.ResultTo
import com.boot.core.util.ManagerKit
import com.boot.mgt.dao.mysql.*
import com.boot.mgt.dao.oracle.OracleTAcdFileMapper
import com.boot.mgt.model.*
import com.boot.mgt.model.vo.EditReportVo
import com.boot.mgt.service.TaAccidentReportService
import com.boot.mgt.service.TaPoliceService
import com.github.pagehelper.PageHelper
import com.github.pagehelper.PageInfo
import com.googlecode.jsonrpc4j.JsonRpcParam
import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl
import org.apache.commons.lang3.time.DateFormatUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.datasource.DriverManagerDataSource
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import tk.mybatis.mapper.entity.Example
import java.util.*


@AutoJsonRpcServiceImpl
@Service
class TaAccidentReportServiceImpl(@Value("\${conf.trafficTaskSource.url}") val url: String,
                                  @Value("\${conf.trafficTaskSource.username}") val name: String,
                                  @Value("\${conf.trafficTaskSource.password}") val pwd: String) : TaAccidentReportService {

    @Autowired
    protected lateinit var accidentReportMapper: TaAccidentReportMapper

    @Autowired
    protected lateinit var accidentMapper: TaAccidentMapper

    @Autowired
    protected lateinit var accidentReportAssignMapper: TaAccidentReportAssignMapper

    @Autowired
    protected lateinit var accidentImageMapper: TaAccidentImageMapper

    @Autowired
    protected lateinit var districtMapper: TaDistrictMapper

    @Autowired
    protected lateinit var streetMapper: TaStreetMapper

    @Autowired
    protected lateinit var addressMapper: TaAddressMapper

    @Autowired
    protected lateinit var policeLogMapper: TaAccidentPoliceLogMapper

    @Autowired
    protected lateinit var oracleTAcdFileMapper: OracleTAcdFileMapper

    @Autowired
    protected lateinit var taAcdFileMapper: TaAcdFileMapper

    @Autowired
    private lateinit var taPoliceService: TaPoliceService

    override fun list(page_index: Int?, page_size: Int?, map: MutableMap<String, Any>): ResultTo {
        PageHelper.startPage<Any>(page_index ?: 1, page_size ?: 20)
        when {
            ManagerKit.isCaptain() -> {
                map["isCaptain"] = true
//                map["orgNum"] = ManagerKit.getOrgNum()
                map["orgNum"] = taPoliceService.consRegion(ManagerKit.getOrgNum()) as String
                map["assigned_police_number"] = ManagerKit.getPoliceNumber()
                val list = accidentReportMapper.policeList(map)
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
            ManagerKit.isOfficer() -> {
//                map["orgNum"] = ManagerKit.getOrgNum()
                map["orgNum"] = taPoliceService.consRegion(ManagerKit.getOrgNum()) as String
                val list = accidentReportMapper.officerList(map)
                if (map["isDistribution"] == "1") {
                    list?.forEach { r ->
                        var re: Map<String, Any> = taPoliceService.searchPoliceById(r.assignedPoliceNumber)
                        r.assignedPoliceName = re["full_name"] as String?
                    }
                }
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
            else -> {
                map["isCaptain"] = false
                map["assigned_police_number"] = ManagerKit.getPoliceNumber()
                val list = accidentReportMapper.policeList(map)
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
        }
    }

    override fun listRpc(page_index: Int?, page_size: Int?, map: MutableMap<String, Any>): ResultTo {
        PageHelper.startPage<Any>(page_index ?: 1, page_size ?: 20)
        val police_level: Int = map["police_level"] as Int
        val org_num: String = map["org_num"] as String
        when (police_level) {
            1 -> {
                map["isCaptain"] = true
                map["orgNum"] = taPoliceService.consRegion(org_num) as String
                map["assigned_police_number"] = map["police_number"] as Any
                val list = accidentReportMapper.policeList(map)
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
            2 -> {
                map["orgNum"] = taPoliceService.consRegion(org_num) as String
                val list = accidentReportMapper.officerList(map)
                if (map["isDistribution"] == "1") {
                    list?.forEach { r ->
                        var re: Map<String, Any> = taPoliceService.searchPoliceById(r.assignedPoliceNumber)
                        r.assignedPoliceName = re["full_name"] as String?
                    }
                }
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
            else -> {
                map["isCaptain"] = false
                map["assigned_police_number"] = map["police_number"] as Any
                val list = accidentReportMapper.policeList(map)
                val pageInfo = PageInfo(list)
                return ResultTo().apply {
                    this["report_list"] = list
                    this["page_index"] = page_index ?: 0
                    this["page_amount"] = pageInfo.pages
                    this["page_total"] = pageInfo.total
                }
            }
        }
    }

    override fun selectForIdMax(): ResultTo {
        val accidentReport = accidentReportMapper.selectVoById(0, 1)
        return ResultTo().setData("accidentReport", accidentReport)
    }

    override fun detail(id: Int, isApp: Boolean): ResultTo {
        val map = hashMapOf<String, Any>()
        val report = accidentReportMapper.selectByPrimaryKey(id)?.apply {

            if (isApp) {
                val example = Example(TaAccidentReportAssign::class.java)
                example.createCriteria()
                        .andEqualTo("accidentReportId", id)
//                        .andEqualTo("assignedPoliceNumber", ManagerKit.getPoliceNumber())
                        .andNotEqualTo("hasAccepted", 3)
                        .andNotEqualTo("hasAccepted", 4)
                accidentReportAssignMapper.selectOneByExample(example)?.let {
                    map["accidentReportAssign"] = it
                }
            } else {
                val accidentReportAssign = TaAccidentReportAssign()
                accidentReportAssign.accidentReportId = id
                accidentReportAssignMapper.select(accidentReportAssign)?.let {
                    if (!it.isEmpty()) {
                        for (taAccidentReportAssign in it) {
                            //modified by liuzhe @2019-03-01
                            if (taAccidentReportAssign.hasAccepted != 0) {
                                map["accidentReportAssign"] = taAccidentReportAssign
                                break
                            } else {
                                map["accidentReportAssign"] = ""
                            }
                        }
                    }
                }
            }
        }
        map["report"] = report ?: TaAccidentReport()
        if (isApp) {
            report?.apply {
                accidentMapper.selectByPrimaryKey(accidentId)?.apply {
                    map["accident"] = this
                    districtMapper.selectByPrimaryKey(districtId)?.let {
                        map["district"] = it
                    }
                    streetMapper.selectByPrimaryKey(streetId)?.let {
                        map["street"] = it
                    }
                    addressMapper.selectByPrimaryKey(addressId)?.let {
                        map["address"] = it
                    }
                    TaAccidentImage().let {
                        it.accidentId = this.id
                        val images = accidentImageMapper.select(it)
                        for (image in images) {
                            image.imageBase64 = null
                        }
                        map["images"] = images
                    }
                }
            }
        }
        return ResultTo().setData(map)
    }

    override fun detailRpc(id: Int): ResultTo {
        val map = hashMapOf<String, Any>()
        val report = accidentReportMapper.selectByPrimaryKey(id)?.apply {
            val example = Example(TaAccidentReportAssign::class.java)
            example.createCriteria()
                    .andEqualTo("accidentReportId", id)
//                        .andEqualTo("assignedPoliceNumber", ManagerKit.getPoliceNumber())
                    .andNotEqualTo("hasAccepted", 3)
                    .andNotEqualTo("hasAccepted", 4)
            accidentReportAssignMapper.selectOneByExample(example)?.let {
                map["accidentReportAssign"] = it
            }
        }
        map["report"] = report ?: TaAccidentReport()
        report?.apply {
            accidentMapper.selectByPrimaryKey(accidentId)?.apply {
                map["accident"] = this
                districtMapper.selectByPrimaryKey(districtId)?.let {
                    map["district"] = it
                }
                streetMapper.selectByPrimaryKey(streetId)?.let {
                    map["street"] = it
                }
                addressMapper.selectByPrimaryKey(addressId)?.let {
                    map["address"] = it
                }
                TaAccidentImage().let {
                    it.accidentId = this.id
                    val images = accidentImageMapper.select(it)
                    for (image in images) {
                        image.imageBase64 = null
                    }
                    map["images"] = images
                }
            }
        }
        return ResultTo().setData(map)
    }

    @Transactional
    override fun edit(editReportVo: EditReportVo): ResultTo {
        editReportVo.xqdw = null
        editReportVo.assignedPoliceNumber?.apply {
            TaAccidentReportAssign().let {
                it.accidentReportId = editReportVo.id
                it.assignedPoliceNumber = editReportVo.assignedPoliceNumber
                accidentReportAssignMapper.selectOne(it)?.let {
                    if (it.hasAccepted == 1) {
                        return ResultTo(ResultEnum.OPERATION_FAILED, "此案件已被接受不能更改接警人")
                    } else {
                        it.assignedPoliceNumber = this
                        accidentReportAssignMapper.updateByPrimaryKeySelective(it)
                    }
                }
            }
        }
        val accidentReport = editReportVo as TaAccidentReport
        log.info("收到数据:${JSON.toJSONString(accidentReport)}")
        with(accidentReport) {
            id?.let {
                log.debug("ID不为Null,编辑报案操作")
                val accidentReportOne = accidentReportMapper.selectByPrimaryKey(id)
                accidentId = accidentReportOne.accidentId
                addTime = accidentReportOne.acceptTime
                type = accidentReportOne.type
                accidentReportMapper.updateByPrimaryKey(accidentReport)
                return ResultTo()
            }
            log.debug("ID为Null,新增报案操作")
            addTime = Date()
            type = 1
            val taAccident = TaAccident().apply {
                state = 2
                accidentId = this.id
                addTime = Date()
            }
            accidentMapper.insertSelective(taAccident)
            accidentReportMapper.insertSelective(this)
            return ResultTo()
        }
    }

    override fun selectForwardLog(accident_report_id: Int): ResultTo {
        val list = accidentReportAssignMapper.selectForwardLog(accident_report_id)
        list.forEach { r ->
            val a = taPoliceService.searchPoliceById(r.policeNumber)
            r.name = a["full_name"] as String?
            r.xqdw = a["region_id"] as String?
        }
        return ResultTo().setData("forwardLog", list)
    }

    override fun ccOperation(accident_report_id: Int, cc_operation_type: String): ResultTo {
        log.info("accident_report_id->" + accident_report_id.toString())
        log.info("cc_operation_type->$cc_operation_type")
        var targetAccidentReport = TaAccidentReport()
        targetAccidentReport.id = accident_report_id
        targetAccidentReport.ccOperationType = cc_operation_type

        accidentReportMapper.updateByPrimaryKeySelective(targetAccidentReport)

        var policeLog = TaAccidentPoliceLog()
        policeLog.addTime = Date()
        policeLog.policeNumber = ManagerKit.getPoliceNumber()
        policeLog.type = 3
        policeLog.reportId = accident_report_id
        policeLog.content = "set cc_operation_type->$cc_operation_type"
        policeLogMapper.insertSelective(policeLog)

        return ResultTo()
    }

    override fun correlation(date: String, oracleTAcdFiles: List<OracleTAcdFile>): ResultTo {
        val list = oracleTAcdFiles.toMutableList()
        val map = mutableMapOf<String, Any>()
        map["startDate"] = "$date 00:00:00"
        map["endDate"] = "$date 23:59:59"
        val accidentReportList = accidentReportMapper.selectCorrelation(map)
        val iterator = list.iterator()
        while (iterator.hasNext()) {
            val taAcdFile = iterator.next()
            for (accidentReport in accidentReportList) {
                if (taAcdFile.djbh.toString() == accidentReport.oracleSgbh) {
                    list.remove(taAcdFile)
                }
            }
            return ResultTo().setData("correlation", list)
        }
        return ResultTo()
    }
//案件确认绑定六合一事故
    override fun checkCorrelation(reportId: Int, oracleTAcdFile: OracleTAcdFile): ResultTo {
        val taAcdFile = oracleTAcdFile as TaAcdFile
        val acdFile = TaAcdFile()
        acdFile.sgbh = taAcdFile.sgbh
       var sgbhTemp:String=taAcdFile.sgbh as String

        val selectOne = taAcdFileMapper.selectOne(acdFile)
        if (selectOne == null) {
            taAcdFileMapper.insertSelective(taAcdFile)
        } else {
            taAcdFile.id = selectOne.id
        }
        val taAccidentReport = accidentReportMapper.selectByPrimaryKey(reportId)
        taAccidentReport.acdFileId = taAcdFile.id
        taAccidentReport.oracleSgbh = taAcdFile.sgbh
        accidentReportMapper.updateByPrimaryKeySelective(taAccidentReport)
        //查询事故是否已经标注,如果已经标注，则退出
    var accidentId:Int=taAccidentReport.accidentId as Int
         if(!this.isInAccidentCoordinate(sgbhTemp)){
             var accidentFile=this.selectAccidentByReportId(accidentId)
             var longitude=accidentFile.amapLongitude
             var latitude=accidentFile.amapLatitude
             var coordinate=longitude.toString()+" "+latitude.toString()
             this.writeInAccidentCoordinate(sgbhTemp,coordinate)
         }
        return ResultTo()
    }

    override fun selectOracleBySgbh(sgbh: String): OracleTAcdFile {
        val dataSource = DriverManagerDataSource()
        dataSource.setDriverClassName("com.mysql.jdbc.Driver")
        dataSource.url = this.url
        dataSource.username = this.name
        dataSource.password = this.pwd
        var result: MutableMap<String, Any> = mutableMapOf()
        val sql = "SELECT taf.* FROM accident_file taf WHERE taf.sgbh = ?"
        try {
            val jdbcTemplate = JdbcTemplate(dataSource)
            result = jdbcTemplate.queryForMap(sql, sgbh)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return BeanUtil.mapToBean(result, OracleTAcdFile::class.java, false)
    }

    @OracleDb
    override fun selectOracleCorrelation(date: String): List<OracleTAcdFile> {
        val map = mutableMapOf<String, Any>()
        map["startDate"] = "$date 00:00:00"
        map["endDate"] = "$date 23:59:59"
        map["orgNum"] = ManagerKit.getOrgNum()
        return oracleTAcdFileMapper.selectByReport(map)
    }

    override fun selectOracleCorrelationRpc(date: String, org_num: String?): ResultTo {
        val map = mutableMapOf<String, Any>()
        map["startDate"] = "$date 00:00:00"
        map["endDate"] = "$date 23:59:59"
        map["orgNum"] = org_num as Any
        //TODO: 原始jdbc难以维护,很不现代化 rankai
        val dataSource = DriverManagerDataSource()
        dataSource.setDriverClassName("com.mysql.jdbc.Driver")
        dataSource.url = this.url
        dataSource.username = this.name
        dataSource.password = this.pwd
        var result: MutableList<MutableMap<String, Any>> = arrayListOf()
        var oracleSgbh=getSgbhFromAccidentReport()
        val sql = "SELECT taf.* FROM accident_file taf WHERE sgbh not in(?) AND  SUBSTR(taf.glbm, 1, 6) =? AND taf.sgfssj BETWEEN ? AND ?"
        System.out.println("需要执行的sql"+sql)
        System.out.println("开始时间"+map["startDate"])
        System.out.println("结束时间"+map["endDate"]+"***org_num.substring(0,6)="+org_num.substring(0,6))
        try {
            val jdbcTemplate = JdbcTemplate(dataSource)
            result = jdbcTemplate.queryForList(sql, oracleSgbh,org_num.substring(0,6), map["startDate"], map["endDate"])
        } catch (e: Exception) {
            e.printStackTrace()
        }
        var mutableList: MutableList<OracleTAcdFile> = mutableListOf()
        for (mutableMap in result) {
            val mapToBean = BeanUtil.mapToBean(mutableMap, OracleTAcdFile::class.java, false)
            mutableList.add(mapToBean)
        }
        System.out.println("查询到的结果长度"+mutableList.size)
        return ResultTo().setData("correlation", mutableList)
    }

    //TODO: 这个方法没必要存在 rankai
    override fun correlationDate(occurTime: Date): String {
        return DateFormatUtils.format(occurTime, "yyyy-MM-dd")
    }


    override fun selectAccidentByReportId(reportId: Int): TaAccident {
        val taAccidentReport = accidentReportMapper.selectByPrimaryKey(reportId)
        return accidentMapper.selectByPrimaryKey(taAccidentReport.accidentId)
    }

    /**
     * 接警中数据列表
     */
    override fun searchCasesAcceptedActioningList(): List<Any?>? {
        return accidentReportMapper.searchCasesAcceptedActioningList()
    }

    /**
     * 勘察中数据列表
     */
    override fun searchCasesSurveyingList(): List<Any?>? {
        return accidentReportMapper.searchCasesSurveyingList()
    }

    /**
     * 事故分布数据列表
     */
    override fun searchTrafficDistributionList(map: Map<String, Any>?): List<Any?>? {
        return accidentReportMapper.searchTrafficDistributionList(map)
    }


    companion object {
        private val log: Logger = LoggerFactory.getLogger(this::class.java)
    }
    //查询案件表中已经绑定的事故编号(sgbh)
    fun getSgbhFromAccidentReport():String{
        var accidentReportList: List<TaAccidentReport?>? = mutableListOf()
        accidentReportList =accidentReportMapper.getAllList();
        var sgbhString=""
        accidentReportList?.forEach { r ->
            sgbhString=r?.oracleSgbh+","+sgbhString

        }
        System.out.print("事故编号"+sgbhString.substring(0,sgbhString.length-1))
        return sgbhString.substring(0,sgbhString.length-1)
    }

//查询事故是否已经标注
    fun isInAccidentCoordinate(sgbh:String): Boolean{
        val dataSource = DriverManagerDataSource()
        dataSource.setDriverClassName("com.mysql.jdbc.Driver")
        dataSource.url = this.url
        dataSource.username = this.name
        dataSource.password = this.pwd
        var result: MutableMap<String, Any> = mutableMapOf()
        val sql = "SELECT * from accident_coordinate where sgbh = ?"
        try {
            val jdbcTemplate = JdbcTemplate(dataSource)
            result = jdbcTemplate.queryForMap(sql, sgbh)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        if(result.size>0){
            return true
        }else{
            return false
        }
    }
     //写入事故坐标
    fun writeInAccidentCoordinate(sgbh:String,coordinate:String): Boolean{
        val dataSource = DriverManagerDataSource()
        dataSource.setDriverClassName("com.mysql.jdbc.Driver")
        dataSource.url = this.url
        dataSource.username = this.name
        dataSource.password = this.pwd
        val insertSql = "INSERT into accident_coordinate (sgbh,coordinate)VALUES(?,?) "
        try {
            val insertjdbcTemplate = JdbcTemplate(dataSource)
            insertjdbcTemplate.update(insertSql,sgbh,coordinate)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return true
    }
}